home *** CD-ROM | disk | FTP | other *** search
/ Aminet 44 / Aminet 44 (2001)(GTI - Schatztruhe)[!][Aug 2001].iso / Aminet / comm / mail / YAM23src.lha / Source / YAM_US.c < prev    next >
C/C++ Source or Header  |  2001-05-08  |  20KB  |  508 lines

  1. /***************************************************************************
  2.  
  3.  YAM - Yet Another Mailer
  4.  Copyright (C) 1995-2000 by Marcel Beck <mbeck@yam.ch>
  5.  Copyright (C) 2000-2001 by YAM Open Source Team
  6.  
  7.  This program is free software; you can redistribute it and/or modify
  8.  it under the terms of the GNU General Public License as published by
  9.  the Free Software Foundation; either version 2 of the License, or
  10.  (at your option) any later version.
  11.  
  12.  This program is distributed in the hope that it will be useful,
  13.  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  GNU General Public License for more details.
  16.  
  17.  You should have received a copy of the GNU General Public License
  18.  along with this program; if not, write to the Free Software
  19.  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  20.  
  21.  YAM Official Support Site :  http://www.yam.ch
  22.  YAM OpenSource project    :  http://sourceforge.net/projects/yamos/
  23.  
  24.  $Id: YAM_US.c,v 1.7 2001/05/08 22:27:37 damato Exp $
  25.  
  26. ***************************************************************************/
  27.  
  28. #include "YAM.h"
  29.  
  30. /* local protos */
  31. LOCAL void US_SaveUsers(void);
  32. LOCAL void US_LoadUsers(void);
  33. LOCAL BOOL US_PromptForPassword(struct User*, APTR);
  34. LOCAL BOOL US_SaveUserList(void);
  35. LOCAL struct US_ClassData *US_New(BOOL);
  36.  
  37. /***************************************************************************
  38.  Module: User list
  39. ***************************************************************************/
  40.  
  41. /// US_GetCurrentUser
  42. //  Gets pointer current user from user database
  43. struct User *US_GetCurrentUser(void)
  44. {
  45.    int i;
  46.    struct User *u = NULL;
  47.    for (i = 0; i < G->Users.Num; i++) if (G->Users.User[i].ID == G->Users.CurrentID) u = &G->Users.User[i];
  48.    return u;
  49. }
  50.  
  51. ///
  52. /// US_SaveUsers
  53. //  Saves user database to .users
  54. LOCAL void US_SaveUsers(void)
  55. {
  56.    FILE *fh;
  57.    char *fname = "PROGDIR:.users";
  58.    int i;
  59.  
  60.    for (i = 0; i < G->Users.Num; i++) if (!G->Users.User[i].Limited) break;
  61.    if (i == G->Users.Num) G->Users.User[0].Limited = FALSE;
  62.    if (fh = fopen(fname, "w"))
  63.    {
  64.       int i;
  65.       fputs("YUS2 - YAM Users\n", fh);
  66.       for (i = 0; i < G->Users.Num; i++)
  67.       {
  68.          struct User *u = &G->Users.User[i];
  69.          if (u->Name) fprintf(fh, "@USER %s\n%s\n%ld\n%s\n@ENDUSER\n", u->Name, u->MailDir, u->Limited*4+u->UseAddr*2+u->UseDict, Encrypt(u->Password));
  70.       }
  71.       fclose(fh);
  72.       AppendLogVerbose(62, GetStr(MSG_LOG_SavingUsers), "", "", "", "");
  73.    }
  74.    else ER_NewError(GetStr(MSG_ER_CantCreateFile), fname, NULL);
  75. }
  76.  
  77. ///
  78. /// US_LoadUsers
  79. //  Loads user database from .users
  80. LOCAL void US_LoadUsers(void)
  81. {
  82.    BOOL save = FALSE;
  83.    FILE *fh;
  84.    char buffer[SIZE_LARGE];
  85.    clear(&G->Users, sizeof(struct Users));
  86.    G->Users.Num = 0;
  87.    if (fh = fopen("PROGDIR:.users", "r"))
  88.    {
  89.       BOOL hasmanager = FALSE;
  90.       GetLine(fh, buffer, SIZE_LARGE);
  91.       if (!strncmp(buffer,"YUS",3))
  92.       {
  93.          int ver = buffer[3]-'0';
  94.          while (GetLine(fh, buffer, SIZE_LARGE))
  95.          {
  96.             if (!strncmp(buffer, "@USER", 5))
  97.             {
  98.                struct User *u = &G->Users.User[G->Users.Num];
  99.                stccpy(u->Name, Trim(&buffer[6]), SIZE_NAME);
  100.                stccpy(u->MailDir, Trim(GetLine(fh, buffer, SIZE_LARGE)), SIZE_PATH);
  101.                if (!*u->MailDir) { stccpy(u->MailDir, G->MA_MailDir, SIZE_PATH); save = TRUE; }
  102.                if (FileType(u->MailDir) != 2)
  103.                {
  104.                   ER_NewError(GetStr(MSG_ER_UserRemoved), u->MailDir, u->Name);
  105.                   u->Name[0] = 0;
  106.                   save = TRUE;
  107.                }
  108.                else
  109.                {
  110.                   int flags = atoi(Trim(GetLine(fh, buffer, SIZE_LARGE)));
  111.                   u->Limited = (flags&4) == 4;
  112.                   u->UseAddr = (flags&2) == 2;
  113.                   u->UseDict = (flags&1) == 1;
  114.                   if (!u->Limited) hasmanager = TRUE;
  115.                   if (ver >= 2) stccpy(u->Password, Decrypt(GetLine(fh, buffer, SIZE_LARGE)), SIZE_PASSWORD);
  116.                   u->ID = GetSimpleID();
  117.                   G->Users.Num++;
  118.                }
  119.                while (GetLine(fh, buffer, SIZE_LARGE)) if (!strcmp(buffer, "@ENDUSER")) break;
  120.             }
  121.          }
  122.       }
  123.       fclose(fh);
  124.       if (!hasmanager) { G->Users.User[0].Limited = FALSE; save = TRUE; }
  125.    }
  126.    if (!G->Users.Num)
  127.    {
  128.       struct User *u = &G->Users.User[0];
  129.       stccpy(u->MailDir, G->MA_MailDir, SIZE_PATH);
  130.       u->UseAddr = u->UseDict = TRUE;
  131.       u->ID = GetSimpleID();
  132.       G->Users.Num = 1;
  133.       save = TRUE;
  134.    }
  135.    if (save) US_SaveUsers();
  136. }
  137.  
  138. ///
  139. /// US_PromptForPassword
  140. //  User login: asks for user password
  141. LOCAL BOOL US_PromptForPassword(struct User *u, APTR win)
  142. {
  143.    char passwd[SIZE_PASSWORD];
  144.  
  145.    do {
  146.       *passwd = 0;
  147.       if (!StringRequest(passwd, SIZE_PASSWORD, GetStr(MSG_US_WaitLogin), GetStr(MSG_US_EnterPassword), GetStr(MSG_Okay), NULL, GetStr(MSG_Cancel), TRUE, win)) return FALSE;
  148.    } while (strcmp(passwd, u->Password));
  149.    return TRUE;
  150. }
  151.  
  152. ///
  153. /// US_Login
  154. //  User login: puts up user list and waits for a selection
  155. BOOL US_Login(char *username, char *password, char *maildir, char *prefsfile)
  156. {
  157.    int i, user = -1;
  158.    APTR button, button0, group;
  159.    struct User *u;
  160.    BOOL loggedin = TRUE;
  161.  
  162.    US_LoadUsers();
  163.    if (username)
  164.    {
  165.       for (i = 0; i < G->Users.Num; i++) if (!stricmp(G->Users.User[i].Name, username)) user = i;
  166.    }
  167.    if (user < 0)
  168.    {
  169.       password = NULL;
  170.       if (G->Users.Num > 1)
  171.          if (DoMethod(G->AY_List, MUIM_Group_InitChange))
  172.          {
  173.             group = ColGroup(2), End;
  174.             for (i = 0; i < G->Users.Num; i++)
  175.             {
  176.                button = MakeButton(G->Users.User[i].Name);
  177.                if (!i) button0 = button;
  178.                DoMethod(group, OM_ADDMEMBER, button);
  179.                DoMethod(button, MUIM_Notify, MUIA_Pressed, FALSE, MUIV_Notify_Application, 2, MUIM_Application_ReturnID, ID_LOGIN+i);
  180.             }
  181.             if (i%2 == 1) DoMethod(group, OM_ADDMEMBER, HSpace(0));
  182.             DoMethod(G->AY_List, OM_ADDMEMBER, group);
  183.             DoMethod(G->AY_List, MUIM_Group_ExitChange);
  184.             set(G->AY_Text, MUIA_ShowMe, TRUE);
  185.             set(G->AY_Text, MUIA_Gauge_InfoText, GetStr(MSG_US_WaitLogin));
  186.             set(G->AY_Group, MUIA_Group_ActivePage, 1);
  187.             set(G->AY_Win, MUIA_Window_ActiveObject, button0);
  188.             set(G->AY_Win, MUIA_Window_Open, TRUE);
  189.             while (user == -1)
  190.             {
  191.                ULONG signals;
  192.                long winopen, iconified;
  193.                get(G->AY_Win, MUIA_Window_Open, &winopen);
  194.                get(G->App, MUIA_Application_Iconified, &iconified);
  195.                if (!winopen && !iconified) return FALSE;
  196.                if ((i = DoMethod(G->App, MUIM_Application_Input, &signals)-ID_LOGIN) >= 0 && i < G->Users.Num) user = i;
  197.                else if (signals) Wait(signals);
  198.             }
  199.             set(G->AY_Group, MUIA_Group_ActivePage, 0);
  200.             DoMethod(G->AY_List, MUIM_Group_InitChange);
  201.             DoMethod(G->AY_List, OM_REMMEMBER, group);
  202.             DoMethod(G->AY_List, MUIM_Group_ExitChange);
  203.          }
  204.          else user = 0;
  205.       else user = 0;
  206.    }
  207.    u = &G->Users.User[user];
  208.    G->Users.CurrentID = u->ID;
  209.    strcpy(G->MA_MailDir, maildir ? maildir : u->MailDir);
  210.    if (prefsfile) strcpy(G->CO_PrefsFile, prefsfile); else strmfp(G->CO_PrefsFile, G->MA_MailDir, ".config");
  211.    strmfp(G->AB_Filename, u->UseAddr ? G->ProgDir : G->MA_MailDir, ".addressbook");
  212.    strmfp(G->DI_Filename, u->UseDict ? G->ProgDir : G->MA_MailDir, ".glossary");
  213.    if (u->Password[0])
  214.       if (password) loggedin = (!strcmp(password, u->Password) || *password == '\01');
  215.       else loggedin = US_PromptForPassword(u, G->AY_Win);
  216.    return loggedin;
  217. }
  218.  
  219. ///
  220. /// US_DelFunc
  221. //  Removes a user from the user database
  222. void SAVEDS US_DelFunc(void)
  223. {
  224.    int i, m;
  225.    struct User *user;
  226.    APTR lv = G->US->GUI.LV_USERS;
  227.    get(lv, MUIA_NList_Active, &i);
  228.    DoMethod(lv, MUIM_NList_GetEntry, i, &user);
  229.    if (*user->MailDir)
  230.    {
  231.       if (!(m = MUI_Request(G->App, G->US->GUI.WI, 0, GetStr(MSG_MA_ConfirmReq), GetStr(MSG_US_RemoveReqGads), GetStr(MSG_US_RemoveReq)))) return;
  232.       if (m == 1) DeleteMailDir(user->MailDir, TRUE);
  233.    }
  234.    DoMethod(lv, MUIM_NList_Remove, i);
  235. }
  236. MakeHook(US_DelHook, US_DelFunc);
  237.  
  238. ///
  239. /// US_AddFunc
  240. //  Adds a new user to the user database
  241. void SAVEDS US_AddFunc(void)
  242. {
  243.    struct US_GUIData *gui = &G->US->GUI;
  244.    struct User user;
  245.    int n;
  246.    get(gui->LV_USERS, MUIA_NList_Entries, &n);
  247.    if (n < MAXUSERS-1)
  248.    {
  249.       clear(&user, sizeof(struct User));
  250.       user.Limited = user.IsNew = TRUE;
  251.       DoMethod(gui->LV_USERS, MUIM_NList_InsertSingle, &user, MUIV_NList_Insert_Bottom);
  252.       set(gui->LV_USERS, MUIA_NList_Active, MUIV_NList_Active_Bottom);
  253.       set(gui->WI, MUIA_Window_ActiveObject, gui->ST_USER);
  254.    }
  255. }
  256. MakeHook(US_AddHook, US_AddFunc);
  257.  
  258. ///
  259. /// US_SaveUserList
  260. //  Initializes configuration files for new users and saves the user database
  261. LOCAL BOOL US_SaveUserList(void)
  262. {
  263.    int i;
  264.  
  265.    get(G->US->GUI.LV_USERS, MUIA_NList_Entries, &G->Users.Num);
  266.    for (i = 0; i < G->Users.Num; i++)
  267.    {
  268.       struct User *u;
  269.       BOOL valid = FALSE;
  270.       DoMethod(G->US->GUI.LV_USERS, MUIM_NList_GetEntry, i, &u);
  271.       G->Users.User[i] = *u;
  272.       if (*u->Name)
  273.          if (*u->MailDir)
  274.             if (FileType(u->MailDir) != 2)
  275.             {
  276.                if (MUI_Request(G->App, G->US->GUI.WI, 0, GetStr(MSG_MA_MUsers), GetStr(MSG_YesNoReq), GetStr(MSG_US_ErrorNoDirectory)))
  277.                   if (CreateDirectory(u->MailDir)) valid = TRUE;
  278.                   else ER_NewError(GetStr(MSG_ER_CantCreateDir), u->MailDir, NULL);
  279.             }
  280.             else valid = TRUE;
  281.          else ER_NewError(GetStr(MSG_ER_MissingDirectory), NULL, NULL);
  282.       else ER_NewError(GetStr(MSG_ER_MissingName), NULL, NULL);
  283.       if (!valid)
  284.       {
  285.          set(G->US->GUI.LV_USERS, MUIA_NList_Active, i);
  286.          return FALSE;
  287.       }
  288.       if (u->Clone && u->IsNew)
  289.       {
  290.          char dest[SIZE_PATHFILE];
  291.          strmfp(dest, u->MailDir, ".addressbook"); CopyFile(dest, NULL, G->AB_Filename, NULL);
  292.          strmfp(dest, u->MailDir, ".glossary");    CopyFile(dest, NULL, G->DI_Filename, NULL);
  293.          strmfp(dest, u->MailDir, ".config");      CopyFile(dest, NULL, G->CO_PrefsFile, NULL);
  294.       }
  295.    }
  296.    US_SaveUsers();
  297.    return TRUE;
  298. }
  299.  
  300. ///
  301. /// US_OpenFunc
  302. //  Opens and initializes user list window
  303. void SAVEDS US_OpenFunc(void)
  304. {
  305.    if (!G->US)
  306.    {
  307.       int i;
  308.       struct User *u;
  309.       for (i = 0; i < G->Users.Num; i++) if (G->Users.User[i].ID == G->Users.CurrentID) u = &G->Users.User[i];
  310.       if (!*G->Users.User[0].Name) stccpy(G->Users.User[0].Name, C->RealName, SIZE_NAME);
  311.       if (!(G->US = US_New(!u->Limited))) return;
  312.       if (!SafeOpenWindow(G->US->GUI.WI)) { DisposeModulePush(&G->US); return; }
  313.       for (i = 0; i < G->Users.Num; i++) DoMethod(G->US->GUI.LV_USERS, MUIM_NList_InsertSingle, &G->Users.User[i], MUIV_NList_Insert_Bottom);
  314.       set(G->US->GUI.LV_USERS, MUIA_NList_Active, 0);
  315.    }
  316. }
  317. MakeHook(US_OpenHook, US_OpenFunc);
  318.  
  319. ///
  320. /// US_CloseFunc
  321. //  Closes user list window
  322. void SAVEDS US_CloseFunc(void)
  323. {
  324.    if (US_SaveUserList()) DisposeModulePush(&G->US);
  325. }
  326. MakeHook(US_CloseHook, US_CloseFunc);
  327.  
  328. ///
  329. /// US_GetUSEntryFunc
  330. //  Fills form with data from selected list entry
  331. void SAVEDS US_GetUSEntryFunc(void)
  332. {
  333.    struct User *user;
  334.    struct US_GUIData *gui = &G->US->GUI;
  335.    BOOL notallowed, iscurrent, limited = !G->US->Supervisor;
  336.    int act;
  337.  
  338.    get(gui->LV_USERS, MUIA_NList_Active, &act);
  339.    if (act != MUIV_NList_Active_Off)
  340.    {
  341.       DoMethod(gui->LV_USERS, MUIM_NList_GetEntry, act, &user);
  342.       iscurrent = user->ID == G->Users.CurrentID;
  343.       nnset(gui->ST_USER,    MUIA_String_Contents, user->Name);
  344.       nnset(gui->ST_MAILDIR, MUIA_String_Contents, user->MailDir);
  345.       nnset(gui->ST_PASSWD,  MUIA_String_Contents, user->Password);
  346.       nnset(gui->CH_USEADDR, MUIA_Selected, user->UseAddr);
  347.       nnset(gui->CH_USEDICT, MUIA_Selected, user->UseDict);
  348.       nnset(gui->CH_ROOT,    MUIA_Selected, !user->Limited);
  349.       nnset(gui->CH_CLONE,   MUIA_Selected, user->Clone);
  350.       notallowed = limited && !iscurrent;
  351.       set(gui->ST_USER,    MUIA_Disabled, notallowed);
  352.       set(gui->CH_USEDICT, MUIA_Disabled, notallowed || !act);
  353.       set(gui->CH_USEADDR, MUIA_Disabled, notallowed || !act);
  354.       set(gui->CH_CLONE,   MUIA_Disabled, !user->IsNew || !act);
  355.       set(gui->PO_MAILDIR, MUIA_Disabled, limited || !act);
  356.       set(gui->CH_ROOT,    MUIA_Disabled, limited);
  357.       set(gui->ST_PASSWD,  MUIA_Disabled, notallowed);
  358.       set(gui->BT_DEL,     MUIA_Disabled, !act || iscurrent);
  359.    }
  360.    else DoMethod(G->App, MUIM_MultiSet, MUIA_Disabled, TRUE, gui->ST_USER, gui->ST_PASSWD, gui->PO_MAILDIR, gui->CH_USEDICT, gui->CH_USEADDR, gui->CH_ROOT, gui->CH_CLONE, gui->BT_DEL, NULL);
  361. }
  362. MakeHook(US_GetUSEntryHook,US_GetUSEntryFunc);
  363.  
  364. ///
  365. /// US_PutUSEntryFunc
  366. //  Fills form data into selected list entry
  367. void SAVEDS US_PutUSEntryFunc(void)
  368. {
  369.    struct User *user = NULL;
  370.    struct US_GUIData *gui = &G->US->GUI;
  371.  
  372.    DoMethod(gui->LV_USERS, MUIM_NList_GetEntry, MUIV_NList_GetEntry_Active, &user);
  373.    if (user)
  374.    {
  375.       GetMUIString(user->Name, gui->ST_USER);
  376.       GetMUIString(user->MailDir, gui->ST_MAILDIR);
  377.       GetMUIString(user->Password, gui->ST_PASSWD);
  378.       user->UseAddr = GetMUICheck(gui->CH_USEADDR);
  379.       user->UseDict = GetMUICheck(gui->CH_USEDICT);
  380.       user->Limited = !GetMUICheck(gui->CH_ROOT);
  381.       user->Clone   = GetMUICheck(gui->CH_CLONE);
  382.       DoMethod(gui->LV_USERS, MUIM_NList_Redraw, MUIV_NList_Redraw_Active);
  383.    }
  384. }
  385. MakeHook(US_PutUSEntryHook,US_PutUSEntryFunc);
  386. ///
  387.  
  388. /*** GUI ***/
  389. /// US_LV_ConFunc
  390. //  User listview construction hook
  391. struct User * SAVEDS ASM US_LV_ConFunc(REG(a1,struct User *user))
  392. {
  393.    struct User *entry = malloc(sizeof(struct User));
  394.    *entry = *user;
  395.    return entry;
  396. }
  397. MakeHook(US_LV_ConHook, US_LV_ConFunc);
  398.  
  399. ///
  400. /// US_LV_DspFunc
  401. //  User listview display hook
  402. long SAVEDS ASM US_LV_DspFunc(REG(a2,char **array), REG(a1,struct User *entry))
  403. {
  404.    if (entry)
  405.    {
  406.       array[0] = entry->Name;
  407.       array[1] = entry->MailDir;
  408.       if (entry->ID == G->Users.CurrentID) array[DISPLAY_ARRAY_MAX] = "\0338";
  409.    }
  410.    else
  411.    {
  412.       array[0] = GetStr(MSG_US_TitleUserName);
  413.       array[1] = GetStr(MSG_US_TitleMailDir);
  414.    }
  415.    return 0;
  416. }
  417. MakeHook(US_LV_DspHook,US_LV_DspFunc);
  418.  
  419. ///
  420. /// US_New
  421. //  Creates user list window
  422. LOCAL struct US_ClassData *US_New(BOOL supervisor)
  423. {
  424.    struct US_ClassData *data;
  425.  
  426.    if (data = calloc(1, sizeof(struct US_ClassData)))
  427.    {
  428.       data->Supervisor = supervisor;
  429.       data->GUI.WI = WindowObject,
  430.          MUIA_Window_Title, GetStr(MSG_MA_MUsers),
  431.          MUIA_HelpNode, "US_W",
  432.          MUIA_Window_ID, MAKE_ID('U','S','E','R'),
  433.          WindowContents, VGroup,
  434.             Child, data->GUI.LV_USERS = NListviewObject,
  435.                MUIA_CycleChain, 1,
  436.                MUIA_NListview_NList, NListObject,
  437.                   InputListFrame,
  438.                   MUIA_NList_ConstructHook, &US_LV_ConHook,
  439.                   MUIA_NList_DestructHook, &GeneralDesHook,
  440.                   MUIA_NList_DisplayHook, &US_LV_DspHook,
  441.                   MUIA_NList_DisplayHook, &MA_LV_FDspFuncHook,
  442.                   MUIA_NList_TitleSeparator, TRUE,
  443.                   MUIA_NList_Title, TRUE,
  444.                   MUIA_NList_Format, "BAR,",
  445.                End,
  446.             End,
  447.             Child, VGroup, GroupFrameT(GetStr(MSG_MA_Settings)),
  448.                Child, ColGroup(2),
  449.                   Child, Label2(GetStr(MSG_US_UserName)),
  450.                   Child, data->GUI.ST_USER = MakeString(SIZE_NAME, GetStr(MSG_US_UserName)),
  451.                   Child, Label2(GetStr(MSG_US_Password)),
  452.                   Child, data->GUI.ST_PASSWD = MakePassString(GetStr(MSG_US_Password)),
  453.                   Child, Label2(GetStr(MSG_US_MailDirectory)),
  454.                   Child, data->GUI.PO_MAILDIR = PopaslObject,
  455.                      MUIA_Popasl_Type,ASL_FileRequest,
  456.                      MUIA_Popstring_String,data->GUI.ST_MAILDIR = MakeString(SIZE_PATH,GetStr(MSG_US_MailDirectory)),
  457.                      MUIA_Popstring_Button,PopButton(MUII_PopDrawer),
  458.                      ASLFR_DrawersOnly, TRUE,
  459.                   End,
  460.                End,
  461.                Child, VGroup,
  462.                   Child, MakeCheckGroup((Object **)&data->GUI.CH_USEADDR, GetStr(MSG_US_GlobalAddrBook)),
  463.                   Child, MakeCheckGroup((Object **)&data->GUI.CH_USEDICT, GetStr(MSG_US_GlobalDict)),
  464.                   Child, MakeCheckGroup((Object **)&data->GUI.CH_ROOT,GetStr(MSG_US_SuperVisor)),
  465.                End,
  466.                Child, VGroup,
  467.                   MUIA_ShowMe, supervisor,
  468.                   Child, MakeCheckGroup((Object **)&data->GUI.CH_CLONE, GetStr(MSG_US_CopyConfig)),
  469.                End,
  470.             End,
  471.             Child, ColGroup(3),
  472.                MUIA_ShowMe, supervisor,
  473.                Child, data->GUI.BT_ADD = MakeButton(GetStr(MSG_US_AddUser)),
  474.                Child, data->GUI.BT_DEL = MakeButton(GetStr(MSG_US_DelUser)),
  475.             End,
  476.          End,
  477.       End;
  478.       if (data->GUI.WI)
  479.       {
  480.          SetHelp(data->GUI.ST_USER   ,MSG_HELP_US_ST_USER);
  481.          SetHelp(data->GUI.ST_MAILDIR,MSG_HELP_US_ST_MAILDIR);
  482.          SetHelp(data->GUI.ST_PASSWD ,MSG_HELP_US_ST_PASSWD);
  483.          SetHelp(data->GUI.CH_USEADDR,MSG_HELP_US_CH_USEADDR);
  484.          SetHelp(data->GUI.CH_USEDICT,MSG_HELP_US_CH_USEDICT);
  485.          SetHelp(data->GUI.CH_CLONE  ,MSG_HELP_US_CH_CLONE);
  486.          SetHelp(data->GUI.CH_ROOT   ,MSG_HELP_US_CH_ROOT);
  487.          SetHelp(data->GUI.BT_ADD    ,MSG_HELP_US_BT_ADD);
  488.          SetHelp(data->GUI.BT_DEL    ,MSG_HELP_US_BT_DEL);
  489.          DoMethod(G->App, OM_ADDMEMBER, data->GUI.WI);
  490.          DoMethod(data->GUI.LV_USERS,  MUIM_Notify,MUIA_List_Active,        MUIV_EveryTime,MUIV_Notify_Application,2,MUIM_CallHook,&US_GetUSEntryHook);
  491.          DoMethod(data->GUI.ST_USER,   MUIM_Notify,MUIA_String_Contents,    MUIV_EveryTime,MUIV_Notify_Application,2,MUIM_CallHook,&US_PutUSEntryHook);
  492.          DoMethod(data->GUI.ST_MAILDIR,MUIM_Notify,MUIA_String_Contents,    MUIV_EveryTime,MUIV_Notify_Application,2,MUIM_CallHook,&US_PutUSEntryHook);
  493.          DoMethod(data->GUI.ST_PASSWD, MUIM_Notify,MUIA_String_Contents,    MUIV_EveryTime,MUIV_Notify_Application,2,MUIM_CallHook,&US_PutUSEntryHook);
  494.          DoMethod(data->GUI.CH_USEADDR,MUIM_Notify,MUIA_Selected,           MUIV_EveryTime,MUIV_Notify_Application,2,MUIM_CallHook,&US_PutUSEntryHook);
  495.          DoMethod(data->GUI.CH_USEDICT,MUIM_Notify,MUIA_Selected,           MUIV_EveryTime,MUIV_Notify_Application,2,MUIM_CallHook,&US_PutUSEntryHook);
  496.          DoMethod(data->GUI.CH_ROOT,   MUIM_Notify,MUIA_Selected,           MUIV_EveryTime,MUIV_Notify_Application,2,MUIM_CallHook,&US_PutUSEntryHook);
  497.          DoMethod(data->GUI.CH_CLONE,  MUIM_Notify,MUIA_Selected,           MUIV_EveryTime,MUIV_Notify_Application,2,MUIM_CallHook,&US_PutUSEntryHook);
  498.          DoMethod(data->GUI.BT_ADD,    MUIM_Notify,MUIA_Pressed,            FALSE         ,MUIV_Notify_Application,2,MUIM_CallHook,&US_AddHook);
  499.          DoMethod(data->GUI.BT_DEL,    MUIM_Notify,MUIA_Pressed,            FALSE         ,MUIV_Notify_Application,2,MUIM_CallHook,&US_DelHook);
  500.          DoMethod(data->GUI.WI,        MUIM_Notify,MUIA_Window_CloseRequest,TRUE          ,MUIV_Notify_Application,2,MUIM_CallHook,&US_CloseHook);
  501.          return data;
  502.       }
  503.       free(data);
  504.    }
  505.    return NULL;
  506. }
  507. ///
  508.